
from typing import Optional, List, Any
from sqlmodel import Field, Relationship, SQLModel
from sqlalchemy import event, JSON, Column, text
from sqlalchemy.types import TypeDecorator, TEXT
from enum import Enum
import json
from models.Base import BaseAndTime
from models.common import get_current_time

from .Link import Role_Menu_Link

# 菜单类型
class MenuTypeEnum(Enum):
    MENU = 0
    IFRAME = 1
    EXTERNAL_LINK = 2
    BUTTON = 3

# 显示链接选项
class ShowLinkEnum(Enum):
    SHOW = True
    HIDE = False

# 固定标签选项
class FixedTagEnum(Enum):
    FIXED = True
    NOT_FIXED = False

# 缓存选项
class KeepAliveEnum(Enum):
    CACHE = True
    NO_CACHE = False

# 隐藏标签选项
class HiddenTagEnum(Enum):
    ALLOW = False
    FORBID = True

# 显示父级菜单选项
class ShowParentEnum(Enum):
    SHOW = True
    HIDE = False

# 框架加载选项
class FrameLoadingEnum(Enum):
    ENABLED = True
    DISABLED = False

# 定义自定义的 JSON 类型转换器
class JSONType(TypeDecorator):
    impl = TEXT

    def process_bind_param(self, value, dialect):
        if value is not None:
            return json.dumps(value)  # 将列表转换为 JSON 字符串
        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            return json.loads(value)  # 将 JSON 字符串转换为列表
        return value
class create_menu(SQLModel):
    menu_type: MenuTypeEnum = Field(default=MenuTypeEnum.MENU, sa_column_kwargs={"nullable": False})
    parent_id: int = Field(default=0, sa_column_kwargs={"nullable": False})
    title: str = Field(default="", max_length=100)
    name: str = Field(default="", max_length=100)
    path: str = Field(default="", max_length=255)
    component: Optional[str] = Field(default="", max_length=255)
    rank: int = Field(default=0)
    redirect: Optional[str] = Field(default="", max_length=255)
    icon: Optional[str] = Field(default="", max_length=255)
    extra_icon: Optional[str] = Field(default="", max_length=255)
    enter_transition: Optional[str] = Field(default="", max_length=255)
    leave_transition: Optional[str] = Field(default="", max_length=255)
    active_path: Optional[str] = Field(default="", max_length=255)
    auths: Optional[str] = Field(default="", max_length=100, index=True)
    frame_src: Optional[str] = Field(default="", max_length=255)
    frame_loading: FrameLoadingEnum = Field(default=FrameLoadingEnum.ENABLED, sa_column_kwargs={"nullable": False})
    keep_alive: KeepAliveEnum = Field(default=KeepAliveEnum.NO_CACHE, sa_column_kwargs={"nullable": False})
    hidden_tag: HiddenTagEnum = Field(default=HiddenTagEnum.ALLOW, sa_column_kwargs={"nullable": False})
    fixed_tag: FixedTagEnum = Field(default=FixedTagEnum.NOT_FIXED, sa_column_kwargs={"nullable": False})
    show_link: ShowLinkEnum = Field(default=ShowLinkEnum.SHOW, sa_column_kwargs={"nullable": False})
    show_parent: ShowParentEnum = Field(default=ShowParentEnum.HIDE, sa_column_kwargs={"nullable": False})

class edit_menu(create_menu):
    id: int = Field(title='菜单ID')

class Menu(BaseAndTime,create_menu, table=True):
    __tablename__ = "sys_menu"  
    higher_menu_options: List[Any] = Field(sa_column=Column(JSON), default=[])
    roles: List["Role"] = Relationship(back_populates="menus", link_model=Role_Menu_Link)

    @property
    def menu_type_text(self)->str:
        if self.menu_type == MenuTypeEnum.MENU:
            return "菜单"
        elif self.menu_type == MenuTypeEnum.IFRAME:
            return "内嵌页面"
        elif self.menu_type == MenuTypeEnum.EXTERNAL_LINK:
            return "外部链接"
        elif self.menu_type == MenuTypeEnum.BUTTON:
            return "按钮"
        return "未知"
    
    @property
    def show_link_text(self)->str:
        if self.show_link == ShowLinkEnum.SHOW:
            return "显示"
        elif self.show_link == ShowLinkEnum.HIDE:
            return "隐藏"
        return "未知"
    
    @property
    def fixed_tag_text(self)->str:
        if self.fixed_tag == FixedTagEnum.FIXED:
            return "固定"
        elif self.fixed_tag == FixedTagEnum.NOT_FIXED:
            return "不固定"
        return "未知"
    
    @property
    def keep_alive_text(self)->str:
        if self.keep_alive == KeepAliveEnum.CACHE:
            return "缓存"
        elif self.keep_alive == KeepAliveEnum.NO_CACHE:
            return "不缓存"
        return "未知"
    
    @property
    def hidden_tag_text(self)->str:
        if self.hidden_tag == HiddenTagEnum.ALLOW:
            return "允许"
        elif self.hidden_tag == HiddenTagEnum.FORBID:
            return "禁止"
        return "未知"
    
    @property
    def show_parent_text(self)->str:
        if self.show_parent == ShowParentEnum.SHOW:
            return "显示"
        elif self.show_parent == ShowParentEnum.HIDE:
            return "隐藏"
        return "未知"
    
    @property
    def frame_loading_text(self)->str:
        if self.frame_loading == FrameLoadingEnum.ENABLED:
            return "启用"
        elif self.frame_loading == FrameLoadingEnum.DISABLED:
            return "禁用"
        return "未知"
    
@event.listens_for(Menu, 'before_update', propagate=True)
def timestamp_before_update(mapper, connection, target):
    target.updatetime = get_current_time()

# 监听 after_insert 事件
@event.listens_for(Menu, 'after_insert', propagate=True)
def rank_after_insert(mapper, connection, target):
    if target.rank == 1:
        # 使用 connection 直接执行 SQL 语句更新 rank 为 id
        update_stmt = text("UPDATE sys_menu SET `rank` = :rank WHERE id = :id")
        connection.execute(update_stmt, {"rank": target.id, "id": target.id})
